package com.appbee.core.server.dao.access.impl;

import javax.inject.Inject;

import com.appbee.core.server.dao.access.CrudAccessControl;
import com.appbee.core.server.dao.access.DeleteAccess;
import com.appbee.core.server.dao.access.IUserControl;
import com.appbee.core.server.dao.access.InsertAccess;
import com.appbee.core.server.dao.access.ReadAccess;
import com.appbee.core.server.dao.access.UpdateAccess;

public class AnnotationCrudAccessControl implements CrudAccessControl
{
	private final IUserControl userControl;

	@Inject
	public AnnotationCrudAccessControl(IUserControl userControl)
	{
		this.userControl = userControl;
	}

	@Override
	public <T> void assertCanDelete(T obj)
	{
		if (userControl.isUserAdmin())
			return;
		DeleteAccess access = obj.getClass().getAnnotation(DeleteAccess.class);
		if (access == null)
			throw new AssertionError("Not accessable");
		assertRole(access.roles());
	}

	@Override
	public <T> void assertCanUpdate(T obj)
	{
		if (userControl.isUserAdmin())
			return;
		UpdateAccess updateAccess = obj.getClass()
				.getAnnotation(UpdateAccess.class);
		if (updateAccess == null)
			throw new AssertionError("Not accessable");
		assertRole(updateAccess.roles());
	}

	@Override
	public <T> void assertCanInsert(T obj)
	{
		if (userControl.isUserAdmin())
			return;
		InsertAccess access = obj.getClass().getAnnotation(InsertAccess.class);
		if (access == null)
			throw new AssertionError("Not accessable");
		assertRole(access.roles());
	}

	@Override
	public <T> void assertCanReadType(Class<T> type)
	{
		if (userControl.isUserAdmin())
			return;
		ReadAccess readAccess = type.getAnnotation(ReadAccess.class);
		if (readAccess == null)
			throw new AssertionError("Not accessable");
		assertRole(readAccess.roles());
	}

	@Override
	public <T> void assertCanRead(T obj)
	{
		assertCanReadType(obj.getClass());
	}

	private <T> void assertRole(String[] roles) throws AssertionError
	{
		if (roles.length == 0)
			return;
		for (String role : roles)
		{
			if (userControl.hasUserRole(role))
				return;
		}
		throw new AssertionError("Not accessable");
	}

}
